home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 2000 November: Tool Chest / Dev.CD Nov 00 TC Disk 1.toast / Sample Code / Archive / Graphics / QuickDraw GX / GX->PostScript Sample / GXToPostScript / PrintingLibraries / ShapeUtilitiesGlyphs.c < prev    next >
Encoding:
Text File  |  2000-09-28  |  21.2 KB  |  571 lines  |  [TEXT/MPS ]

  1. /*
  2.      File:        ShapeUtilitiesGlyphs.c
  3.  
  4.      Contains:    QuickDraw GX to PostScript conversion code.
  5.  
  6.      Version:    Technology:    Quickdraw GX 1.1.x
  7.       
  8.      Copyright:    © 1989-1997 by Apple Computer, Inc., all rights reserved.
  9. */
  10.  
  11. #undef CHECK_OWNER_COUNT                // Check owner counts before disposing
  12. #undef CREATE_NEW_GLYPH                    // New glyph shape vs copy and modify original
  13. #undef NOT_GETPARTS                        // GetShapeParts vs old way
  14. #undef OLD_BUCKETS                        // Use old bucket creation scheme
  15. #undef SKIA_BUG_2PICTURE                // Converting to picture doubles transform (mapping)
  16.  
  17. #include "GXToPSBuildConfig.h"
  18. #include <GXGraphics.h>
  19. #include "GXExceptions.h"
  20. #include "ShapeUtilities.h"
  21. #include "IOUtilities.h"
  22.  
  23.  
  24. /* Chop that glyph! */
  25. OSErr ShUDissectGlyphs(gxShape theShape, Boolean splitByStyle)
  26. {
  27.     OSErr status;
  28.     gxShape theSource, thisShape;
  29. #ifdef NOT_GETPARTS
  30. #if debugon
  31.     long glyphIndex = 0;
  32. #endif debugon
  33.  
  34.     short shortOfOne = 1;
  35.     long longOfOne = 1;
  36.     long longAllBitsSet = 0xFFFFFFFF;
  37.     long runLength;
  38.     long textByteCount, theLength, theRuns;
  39.     Ptr theBlock;
  40.     Ptr theText;
  41.     short *theStyleRuns;
  42.     long *theAdvanceBits;
  43.     gxPoint *thePositions, *theTangents;
  44.     gxStyle *theGlyphStyles;
  45. #ifdef CREATE_NEW_GLYPH
  46.     gxStyle theDefaultStyle;
  47.     gxTransform theDefaultTransform;
  48.     gxInk theDefaultInk;
  49. #endif CREATE_NEW_GLYPH
  50. #ifdef OLD_BUCKETS
  51.     short runCount;
  52.     gxTransform identityTransform;
  53. #endif OLD_BUCKETS
  54.     short advanceArraySize;    /* Max size of advance bits array */
  55.     short charCodeSize;    /* Size of each character code in text stream */
  56.  
  57.     /* Validate shape type */
  58.     switch (GXGetShapeType(theShape)) {
  59.         case gxTextType:
  60.             /* Check for simple text shape short-cut */
  61.             theLength = GXGetText(theShape, nil, nil, nil);
  62.             nrequire(status = GXGetGraphicsError(nil), failed_GetText);
  63.             if (theLength < 2  ||  splitByStyle)    /* Only has one style run! */
  64.                 return(shape_already_in_simple_form);
  65.             GXSetShapeType(theShape, gxGlyphType);    /* Convert to glyph */
  66.             break;
  67.         case gxLayoutType:
  68.             /* Check for simple layout shape short-cut */
  69.             theLength = GXGetLayout(theShape, nil, nil, nil, nil, &runCount, nil, nil, nil, nil);
  70.             nrequire(status = GXGetGraphicsError(nil), failed_GetLayout);
  71.             if (theLength < 2  ||  (splitByStyle  &&  runCount < 2))
  72.                 return(shape_already_in_simple_form);
  73.             GXPrimitiveShape(theShape);                /* Convert to glyph with layout applied */
  74.             check(GXGetShapeType(theShape) == gxGlyphType);
  75.             break;
  76.         case gxGlyphType:
  77.             break;    /* These are great! */
  78.         default:
  79.             status = illegal_type_for_shape;    /* Give reason */
  80.             GXPostGraphicsError(status);    /* Yell real loud! */
  81.             nrequire(status, failed_WrongShape);    /* Bail out */
  82.     }
  83.     nrequire(status = GXGetGraphicsError(nil), failed_ShapeType);
  84.  
  85.     /* Get the sizes */
  86.     textByteCount = GXGetGlyphs(theShape, &theLength, nil, nil, nil, nil, &theRuns, nil, nil);
  87.     nrequire(status = GXGetGraphicsError(nil), failed_GetGlyphs1);
  88.     advanceArraySize = splitByStyle ? (1 + ((theLength - 1) / (8 * sizeof(long)))) : 0;    /* Calculate max array size */
  89.  
  90.     /* Check for simple shape short-cut */
  91.     if (theLength < 2  ||  (splitByStyle  &&  theRuns < 2))
  92.         return(shape_already_in_simple_form);
  93.  
  94. #ifdef OLD_BUCKETS
  95.     theSource = GXCopyToShape(nil, theShape);    /* Make a working copy */
  96.     nrequire(status = GXGetGraphicsError(nil), failed_CopyToShape);
  97.  
  98.     identityTransform = GXNewTransform();    /* Identity transform */
  99.     nrequire(status = GXGetGraphicsError(nil), failed_NewTransform);
  100.     GXSetShapeTransform(theSource, identityTransform);    /* Just one mapping, please! */
  101.     GXDisposeTransform(identityTransform);    /* Clean up */
  102.     nrequire(status = GXGetGraphicsError(nil), failed_DisposeTransform);
  103.  
  104.     GXSetShapeType(theShape, gxPictureType);    /* Create return bucket */
  105.     nrequire(status = GXGetGraphicsError(nil), failed_SetShapeType);
  106.     GXSetPictureParts(theShape, 1, 1, 0, nil, nil, nil, nil);    /* Clean it out */
  107.     nrequire(status = GXGetGraphicsError(nil), failed_SetPictureParts);
  108. #else OLD_BUCKETS
  109.     GXSetShapeType(theShape, gxPictureType);    /* Create return bucket */
  110.     nrequire(status = GXGetGraphicsError(nil), failed_SetShapeType);
  111.     GXGetPictureParts(theShape, 1, 1, &thisShape, nil, nil, nil);    /* Extract shape */
  112.     nrequire(status = GXGetGraphicsError(nil), failed_GetPictureParts);
  113.  
  114.     theSource = GXCloneShape(thisShape);    /* Make a (clone) copy */
  115.     nrequire(status = GXGetGraphicsError(nil), failed_CloneShape);
  116.  
  117. # ifdef CHECK_OWNER_COUNT
  118.     check(GXGetShapeOwners(thisShape) == 2);    /* Pre-SetPictureParts() value */
  119. # endif CHECK_OWNER_COUNT
  120.     GXSetPictureParts(theShape, 1, 1, 0, nil, nil, nil, nil);    /* Clean it out */
  121.     nrequire(status = GXGetGraphicsError(nil), failed_SetPictureParts);
  122. # ifdef CHECK_OWNER_COUNT
  123.     check(GXGetShapeOwners(theSource) == 1);    /* Post-SetPictureParts() value */
  124. # endif CHECK_OWNER_COUNT
  125. #endif OLD_BUCKETS
  126.  
  127.     /* Create a block in this form:
  128.         theText = (void *) NewPtr(textByteCount);
  129.         thePositions = (gxPoint *) NewPtr((theLength + 1) * sizeof(gxPoint));
  130.         theAdvanceBits = (long *) NewPtr(advanceArraySize * sizeof(long));
  131.         theTangents = (gxPoint *) NewPtr(theLength * sizeof(gxPoint));
  132.         theStyleRuns = (short *) NewPtr(theRuns * sizeof(short));
  133.         theGlyphStyles = (gxStyle *) NewPtr(theRuns * sizeof(gxStyle));
  134.     */
  135.     status = PrNewPtr(&theBlock
  136.             (textByteCount +                        /* Text */
  137.             (advanceArraySize * sizeof(long)) +    /* Advance bits */
  138.             sizeof(point) +                        /* Extra entry for thePositions */
  139.             (theLength * (sizeof(gxPoint) + sizeof(gxPoint))) +
  140.             (theRuns * (sizeof(short) + sizeof(gxStyle))))
  141.         );
  142.     nrequire(status, failed_NewPtr);
  143.  
  144.     /* Set the pointers */
  145.     theTangents = (gxPoint *) theBlock;
  146.     thePositions = (gxPoint *) (((Ptr)theTangents) + (theLength * sizeof(gxPoint)));
  147.     theGlyphStyles = (gxStyle *) (((Ptr)thePositions) + ((theLength + 1) * sizeof(gxPoint)));
  148.     theStyleRuns = (short *) (((Ptr)theGlyphStyles) + (theRuns * sizeof(gxStyle)));
  149.     theAdvanceBits = (long *) (((Ptr)theStyleRuns) + (theRuns * sizeof(short)));
  150.     theText = (Ptr) (((Ptr)theAdvanceBits) + (advanceArraySize * sizeof(long)));
  151.  
  152.     /* Check pointer arithmetic (end bytes should match) */
  153.     check((theBlock + GetPtrSize(theBlock)) == (((Ptr)theText) + textByteCount));
  154.  
  155.     GXGetGlyphMetrics(theSource, thePositions, nil, nil);    /* Get absolute positions of glyphs */
  156.     nrequire(status = GXGetGraphicsError(nil), failed_GetGlyphMetrics);
  157.  
  158. GXIgnoreGraphicsNotice(glyph_tangents_have_no_effect);    /* Style may already be set */
  159.     GXGetGlyphs(theSource, nil, theText, nil, nil, theTangents, nil, theStyleRuns, theGlyphStyles);    /* Get the real meat */
  160. GXPopGraphicsNotice();    /* Start warning again */
  161.     nrequire(status = GXGetGraphicsError(nil), failed_GetGlyphs2);
  162.  
  163.     charCodeSize = textByteCount / theLength;    /* Average character size */
  164.     check((long) charCodeSize * theLength == textByteCount);    /* Only accurate for consistent size platform styles */
  165.  
  166. #ifdef CREATE_NEW_GLYPH
  167.     /* Get shape defaults */
  168.     theDefaultStyle = GXGetShapeStyle(theSource);
  169.     theDefaultTransform = GXGetShapeTransform(theSource);
  170.     theDefaultInk = GXGetShapeInk(theSource);
  171. #endif CREATE_NEW_GLYPH
  172.  
  173.     if (splitByStyle) {    /* Split each style run into separate picture element */
  174.         for ( ; --advanceArraySize >= 0 ; )    /* Initialize max array */
  175.             theAdvanceBits[advanceArraySize] = longAllBitsSet;
  176.         for ( ; --theRuns >= 0 ; ) {    /* Loop through run styles */
  177.             runLength = *theStyleRuns;    /* Needs to pass a (long *) */
  178. #ifdef CREATE_NEW_GLYPH
  179.             thisShape = GXNewGlyphs(runLength, theText, thePositions, theAdvanceBits, theTangents, theStyleRuns++, theGlyphStyles++);    /* Make new one */
  180.             nrequire(status = GXGetGraphicsError(nil), failed_NewGlyphs2);
  181. GXIgnoreGraphicsNotice(style_already_set);    /* Style may already be set */
  182.             GXSetShapeStyle(thisShape, theDefaultStyle);
  183. GXPopGraphicsNotice();    /* Start warning again */
  184. GXIgnoreGraphicsNotice(transform_already_set);    /* Transform may already be set */
  185.             GXSetShapeTransform(thisShape, theDefaultTransform);
  186. GXPopGraphicsNotice();    /* Start warning again */
  187. GXIgnoreGraphicsNotice(ink_already_set);    /* Ink may already be set */
  188.             GXSetShapeInk(thisShape, theDefaultInk);
  189. GXPopGraphicsNotice();    /* Start warning again */
  190.             nrequire(status = GXGetGraphicsError(nil), failed_SetShapeDefaults2);
  191. #else CREATE_NEW_GLYPH
  192.             thisShape = GXCopyToShape(nil, theSource);    /* To insure proper default style, transform, and ink */
  193.             nrequire(status = GXGetGraphicsError(nil), failed_NewGlyphs2);
  194.             GXSetGlyphs(thisShape, runLength, theText, thePositions, theAdvanceBits, theTangents, theStyleRuns++, theGlyphStyles++);    /* Override glyph */
  195.             nrequire(status = GXGetGraphicsError(nil), failed_SetGlyphs2);
  196. #endif CREATE_NEW_GLYPH
  197. #ifdef CHECK_OWNER_COUNT
  198.             check(GXGetShapeOwners(thisShape) == 1);    /* Pre-SetPictureParts() value */
  199. #endif CHECK_OWNER_COUNT
  200.             GXSetPictureParts(theShape, 0, 0, 1, &thisShape, nil, nil, nil);    /* Append the part */
  201.             nrequire(status = GXGetGraphicsError(nil), failed_AddToPicture2);
  202. #ifdef CHECK_OWNER_COUNT
  203.             check(GXGetShapeOwners(thisShape) == 2);    /* Post-SetPictureParts() value */
  204. #endif CHECK_OWNER_COUNT
  205.             GXDisposeShape(thisShape);    /* Don't litter! */
  206.             theText += ((short) runLength * charCodeSize);    /* Advance to next byte (DEPENDS on PLATFORM!) */
  207.             thePositions += runLength;    /* Advance positions */
  208.             theTangents += runLength;    /* Advance tangents */
  209. #if debugon
  210.             glyphIndex += runLength;    /* Increase glyph count */
  211. #endif debugon
  212.         }
  213.     }
  214.     else {    /* Split each glyph into separate picture element */
  215.         for ( ; --theRuns >= 0 ; ) {    /* Loop through run styles */
  216.             for (runCount = *(theStyleRuns++) - 1; runCount >= 0; --runCount) {    /* Repeat for the run */
  217. #ifdef CREATE_NEW_GLYPH
  218.                 thisShape = GXNewGlyphs(longOfOne, theText, thePositions++, &longAllBitsSet, theTangents++, &shortOfOne, theGlyphStyles);    /* Make new one */
  219.                 nrequire(status = GXGetGraphicsError(nil), failed_NewGlyphs);
  220. GXIgnoreGraphicsNotice(style_already_set);    /* Style may already be set */
  221.                 GXSetShapeStyle(thisShape, theDefaultStyle);
  222. GXPopGraphicsNotice();    /* Start warning again */
  223. GXIgnoreGraphicsNotice(transform_already_set);    /* Transform may already be set */
  224.                 GXSetShapeTransform(thisShape, theDefaultTransform);
  225. GXPopGraphicsNotice();    /* Start warning again */
  226. GXIgnoreGraphicsNotice(ink_already_set);    /* Ink may already be set */
  227.                 GXSetShapeInk(thisShape, theDefaultInk);
  228. GXPopGraphicsNotice();    /* Start warning again */
  229.                 nrequire(status = GXGetGraphicsError(nil), failed_SetShapeDefaults);
  230. #else CREATE_NEW_GLYPH
  231.                 thisShape = GXCopyToShape(nil, theSource);    /* To insure proper default style, transform, and ink */
  232.                 nrequire(status = GXGetGraphicsError(nil), failed_NewGlyphs);
  233.                 GXSetGlyphs(thisShape, longOfOne, theText, thePositions++, &longAllBitsSet, theTangents++, &shortOfOne, theGlyphStyles);    /* Override glyph */
  234.                 nrequire(status = GXGetGraphicsError(nil), failed_SetGlyphs);
  235. #endif CREATE_NEW_GLYPH
  236. #ifdef CHECK_OWNER_COUNT
  237.                 check(GXGetShapeOwners(thisShape) == 1);    /* Pre-SetPictureParts() value */
  238. #endif CHECK_OWNER_COUNT
  239.                 GXSetPictureParts(theShape, 0, 0, 1, &thisShape, nil, nil, nil);    /* Append the part */
  240.                 nrequire(status = GXGetGraphicsError(nil), failed_AddToPicture);
  241. #ifdef CHECK_OWNER_COUNT
  242.                 check(GXGetShapeOwners(thisShape) == 2);    /* Post-SetPictureParts() value */
  243. #endif CHECK_OWNER_COUNT
  244.                 GXDisposeShape(thisShape);    /* Don't litter! */
  245.                 theText += charCodeSize;    /* Advance to next byte (DEPENDS on PLATFORM!) */
  246. #if debugon
  247.                 ++glyphIndex;    /* Next glyph */
  248. #endif debugon
  249.             }
  250.             ++theGlyphStyles;    /* Next style in run */
  251.         }
  252.     }
  253.  
  254.     check(glyphIndex == theLength);    /* Correct number of glyphs? */
  255.     check((theBlock + GetPtrSize(theBlock)) == ((Ptr)theText));    /* Correct text length? */
  256.  
  257.     (void) PrDisposePtr(theBlock);    /* Don't litter! */
  258. #ifdef CHECK_OWNER_COUNT
  259.     check(GXGetShapeOwners(theSource) == 1);    /* Disposing last reference */
  260. #endif CHECK_OWNER_COUNT
  261.     GXDisposeShape(theSource);    /* Don't litter! */
  262.     return(noErr);    /* OK */
  263.  
  264.     /* BAILOUTS */
  265. failed_AddToPicture2:
  266. failed_AddToPicture:
  267. failed_SetShapeDefaults2:
  268. failed_SetShapeDefaults:
  269. failed_NewGlyphs2:
  270. failed_NewGlyphs:
  271. failed_SetGlyphs2:
  272. failed_SetGlyphs:
  273. failed_GetGlyphs2:
  274. failed_GetGlyphMetrics:
  275.     (void) PrDisposePtr(theBlock);    /* Don't litter! */
  276. failed_NewPtr:
  277. failed_SetPictureParts:
  278. failed_DisposeTransform:
  279. failed_NewTransform:
  280.     DisposeShape(theSource);    /* Don't litter! */
  281. failed_CopyToShape:
  282. failed_CloneShape:
  283. failed_GetPictureParts:
  284. failed_SetShapeType:
  285. failed_GetGlyphs1:
  286. failed_ShapeType:
  287. failed_WrongShape:
  288. failed_GetLayout:
  289. failed_GetText:
  290.  
  291. #else NOT_GETPARTS
  292.     long glyphIndex = 1;
  293.     long runLength;
  294.     long textByteCount, theLength, theRuns;
  295.     Ptr theBlock = NULL;
  296.     short *theStyleRuns;
  297. #ifdef OLD_BUCKETS
  298.     transform identityTransform;
  299. #endif OLD_BUCKETS
  300.  
  301.     /* Validate shape type and get the sizes */
  302.     switch (GXGetShapeType(theShape)) {
  303.         case gxTextType:
  304.             GXGetText(theShape, &theLength, nil, nil);
  305.             theRuns = 1;    /* Text has only one style */
  306.             break;
  307.         case gxLayoutType:
  308.             GXSetShapeAttributes(theShape, GXGetShapeAttributes(theShape) + gxNoMetricsGridShape);
  309.             GXPrimitiveShape(theShape);            // convert it to a glyph shape.
  310.             check(GXGetShapeType(theShape) == gxGlyphType);
  311.             /** Fall through to glyph case **/
  312.         case gxGlyphType:
  313.             textByteCount = GXGetGlyphs(theShape, &theLength, nil, nil, nil, nil, &theRuns, nil, nil);
  314.             break;    /* These are great! */
  315.         default:
  316.             status = illegal_type_for_shape;    /* Give reason */
  317.             GXPostGraphicsError(status);    /* Yell real loud! */
  318.             nrequire(status, failed_WrongShape);    /* Bail out */
  319.     }
  320.     nrequire(status = GXGetGraphicsError(nil), failed_ShapeType);
  321.  
  322.     /* Check for simple shape short-cut */
  323.     if (theLength < 2  ||  (splitByStyle  &&  theRuns < 2))
  324.         return(shape_already_in_simple_form);
  325.  
  326. #ifdef OLD_BUCKETS
  327.     theSource = GXCopyToShape(nil, theShape);    /* Make a working copy */
  328.     nrequire(status = GXGetGraphicsError(nil), failed_CopyToShape);
  329.  
  330.     identityTransform = GXNewTransform();    /* Identity transform */
  331.     nrequire(status = GXGetGraphicsError(nil), failed_NewTransform);
  332.     GXSetShapeTransform(theSource, identityTransform);    /* Just one mapping, please! */
  333.     GXDisposeTransform(identityTransform);    /* Clean up */
  334.     nrequire(status = GXGetGraphicsError(nil), failed_DisposeTransform);
  335.  
  336.     GXSetShapeType(theShape, gxPictureType);    /* Create return bucket */
  337.     nrequire(status = GXGetGraphicsError(nil), failed_SetShapeType);
  338.     GXSetPictureParts(theShape, 1, 1, 0, nil, nil, nil, nil);    /* Clean it out */
  339.     nrequire(status = GXGetGraphicsError(nil), failed_SetPictureParts);
  340. #else OLD_BUCKETS
  341.     GXSetShapeType(theShape, gxPictureType);    /* Create return bucket */
  342.     nrequire(status = GXGetGraphicsError(nil), failed_SetShapeType);
  343.     GXGetPictureParts(theShape, 1, 1, &thisShape, nil, nil, nil);    /* Extract shape */
  344.     nrequire(status = GXGetGraphicsError(nil), failed_GetPictureParts);
  345.  
  346.     theSource = GXCloneShape(thisShape);    /* Make a (clone) copy */
  347.     nrequire(status = GXGetGraphicsError(nil), failed_CloneShape);
  348.     
  349. #ifdef REMOVE
  350. // gx graphics used to double-transform picture shapes -- we fixed
  351. // this in gx graphics on 1/19/94
  352.     {
  353.         gxTransform identityTransform;
  354.         
  355.         identityTransform = GXNewTransform();    /* Identity transform */
  356.         nrequire(status = GXGetGraphicsError(nil), failed_NewTransform);
  357.         GXSetShapeTransform(theSource, identityTransform);    /* Just one mapping, please! */
  358.         GXDisposeTransform(identityTransform);    /* Clean up */
  359.         nrequire(status = GXGetGraphicsError(nil), failed_DisposeTransform);
  360.     }
  361. #endif
  362.  
  363. # ifdef CHECK_OWNER_COUNT
  364.     check(GXGetShapeOwners(thisShape) == 2);    /* Pre-SetPictureParts() value */
  365. # endif CHECK_OWNER_COUNT
  366.     GXSetPictureParts(theShape, 1, 1, 0, nil, nil, nil, nil);    /* Clean it out */
  367.     nrequire(status = GXGetGraphicsError(nil), failed_SetPictureParts);
  368. # ifdef CHECK_OWNER_COUNT
  369.     check(GXGetShapeOwners(theSource) == 1);    /* Post-SetPictureParts() value */
  370. # endif CHECK_OWNER_COUNT
  371. #endif OLD_BUCKETS
  372.  
  373.     if (splitByStyle) {    /* Split each style run into separate picture element */
  374.         status = PrNewPtr(&theBlock, (theRuns * sizeof(short)));
  375.         theStyleRuns = (short *) theBlock;
  376.         nrequire(status, failed_NewPtr);
  377.  
  378.         GXGetGlyphs(theSource, nil, nil, nil, nil, nil, nil, theStyleRuns, nil);    /* Get the real meat */
  379.         nrequire(status = GXGetGraphicsError(nil), failed_GetGlyphs2);
  380.  
  381.         for ( ; --theRuns >= 0 ; ) {    /* Loop through run styles */
  382.             runLength = *(theStyleRuns++);    /* Needs to pass a (long *) */
  383.  
  384.             check (runLength > 0);    /* Is this test needed? */
  385.             if (runLength > 0) {
  386.                 thisShape = GXGetShapeParts(theSource, glyphIndex, runLength, nil);
  387.                 nrequire(status = GXGetGraphicsError(nil), failed_GetShapeParts2);
  388.  
  389. #ifdef CHECK_OWNER_COUNT
  390.                 check(GXGetShapeOwners(thisShape) == 1);    /* Pre-SetPictureParts() value */
  391. #endif CHECK_OWNER_COUNT
  392.                 GXSetPictureParts(theShape, 0, 0, 1, &thisShape, nil, nil, nil);    /* Append the part */
  393.                 nrequire(status = GXGetGraphicsError(nil), failed_AddToPicture2);
  394. #ifdef CHECK_OWNER_COUNT
  395.                 check(GXGetShapeOwners(thisShape) == 2);    /* Post-SetPictureParts() value */
  396. #endif CHECK_OWNER_COUNT
  397.  
  398.                 GXDisposeShape(thisShape);    /* Don't litter! */
  399.  
  400.                 glyphIndex += runLength;    /* Increase glyph count */
  401.             }
  402.         }
  403.         check (theStyleRuns = &((short *) theBlock)[theRuns]);
  404.         DisposePtr(theBlock);    /* Don't litter! */
  405.         theBlock = NULL;
  406.     }
  407.     else {    /* Split each glyph into separate picture element */
  408.         for (; glyphIndex <= theLength; ) {    /* Loop through glyphs */
  409.             thisShape = GXGetShapeParts(theSource, glyphIndex++, 1, nil);
  410.             nrequire(status = GXGetGraphicsError(nil), failed_GetShapeParts);
  411.  
  412. #ifdef CHECK_OWNER_COUNT
  413.             check(GXGetShapeOwners(thisShape) == 1);    /* Pre-SetPictureParts() value */
  414. #endif CHECK_OWNER_COUNT
  415.             GXSetPictureParts(theShape, 0, 0, 1, &thisShape, nil, nil, nil);    /* Append the part */
  416.             nrequire(status = GXGetGraphicsError(nil), failed_AddToPicture);
  417. #ifdef CHECK_OWNER_COUNT
  418.             check(GXGetShapeOwners(thisShape) == 2);    /* Post-SetPictureParts() value */
  419. #endif CHECK_OWNER_COUNT
  420.  
  421.             GXDisposeShape(thisShape);    /* Don't litter! */
  422.         }
  423.     }
  424.  
  425.     check((glyphIndex - 1) == theLength);    /* Correct number of glyphs? */
  426.  
  427. #ifdef CHECK_OWNER_COUNT
  428.     check(GXGetShapeOwners(theSource) == 1);    /* Disposing last reference */
  429. #endif CHECK_OWNER_COUNT
  430.     GXDisposeShape(theSource);    /* Don't litter! */
  431.  
  432.     return(noErr);    /* OK */
  433.  
  434.  
  435.     /* BAILOUTS */
  436. failed_AddToPicture2:
  437. failed_AddToPicture:
  438. failed_GetShapeParts2:
  439. failed_GetShapeParts:
  440. failed_GetGlyphs2:
  441.     if (theBlock)
  442.         DisposePtr(theBlock);    /* Don't litter! */
  443.  
  444. failed_NewPtr:
  445. failed_SetPictureParts:
  446. failed_DisposeTransform:
  447. failed_NewTransform:
  448.     GXDisposeShape(theSource);    /* Don't litter! */
  449. failed_CopyToShape:
  450. failed_CloneShape:
  451. failed_GetPictureParts:
  452. failed_SetShapeType:
  453. failed_ShapeType:
  454. failed_WrongShape:
  455. #endif NOT_GETPARTS
  456.  
  457.     return(status);    /* Propagate error */
  458. }
  459.  
  460.  
  461.  
  462.  
  463.  
  464. /***************************************************
  465.  
  466.     Function:    TextToUnhintedPath
  467.     
  468.     Function converts a text/layout/glyph shape into
  469.     an unhinted path with ideal metrics.
  470.  
  471.     All styles that need to be modified are copied so any shared
  472.     references aren't affected.
  473.  
  474. ****************************************************/
  475. OSErr TextToUnhintedPath(gxShape target)
  476.     {
  477.         OSErr                    status = noErr;
  478.         gxShapeType            theType;
  479.         gxStyle                aStyle;
  480.         gxStyle                *styles, *pStyle;
  481.         gxTextAttribute    *oldAttributes, *pAttributes, oldMainAttributes;
  482.         long                    nStyles, i, charCount;
  483.  
  484.         theType = GXGetShapeType(target);
  485.  
  486.         // Make sure metrics are unhinted for shape's main style.
  487.  
  488.         aStyle = GXGetShapeStyle(target);
  489.         oldMainAttributes = GXGetStyleTextAttributes( aStyle );
  490.         GXSetStyleTextAttributes(aStyle, oldMainAttributes | gxNoContourGridText | gxNoMetricsGridText );
  491.  
  492.         switch(theType) {
  493.         
  494.             case    gxTextType:
  495.                 GXSetShapeType(target, gxPathType);
  496.                 break;
  497.             
  498.             case    gxLayoutType:
  499.                 GXPrimitiveShape(target);                    // try to convert it to a glyph shape
  500.                 theType = GXGetShapeType(target);        // if there were no glyphs, it will be empty.
  501.                 if (theType == gxEmptyType)                // so we fall out.
  502.                     break;
  503.                 
  504.                 // otherwise fall through to glyph case (assuming it is glyph)
  505.             
  506.             case    gxGlyphType:
  507.                 // Get memory for the styles and the style's text attributes
  508.                 GXGetGlyphs(target, &charCount, nil, nil, nil, nil, &nStyles, nil, nil);
  509.                 nrequire(status = GXGetGraphicsError(nil), failed_GetGlyphs);
  510.                 
  511.                 status = PrNewPtr((Ptr *) &styles, nStyles * (sizeof(gxStyle) + sizeof(gxTextAttribute)) );
  512.                 nrequire(status, failed_newptr);
  513.                 
  514.                 oldAttributes = (gxTextAttribute*) ( (Ptr)styles + nStyles * sizeof(gxStyle) );
  515.                 
  516.                 GXGetGlyphs(target, nil, nil, nil, nil, nil, nil, nil, styles);
  517.                 nrequire(status = GXGetGraphicsError(nil), failed_GetGlyphs1);
  518.  
  519.                 /* Turn off hinting for all styles in shape */
  520.  
  521.                 pStyle = styles;
  522.                 pAttributes = oldAttributes;
  523.                 for (i = 0; i < nStyles; ++i, ++pStyle, ++pAttributes) {
  524.                 
  525.                     if (*pStyle != nil) {
  526.                         
  527.                         *pAttributes = GXGetStyleTextAttributes(*pStyle);
  528.                         GXSetStyleTextAttributes(*pStyle, *pAttributes | gxNoContourGridText | gxNoMetricsGridText );
  529.                         
  530.                     }//end if
  531.                 
  532.                 }//end for
  533.                                 
  534.                 // Now, Convert it to a path.
  535.                 
  536.                 GXSetShapeType( target, gxPathType );
  537.                 nrequire(status = GXGetGraphicsError(nil), failed_changeType);
  538.  
  539.                 
  540.                 // Now restore the old attributes
  541.                 
  542.                 pStyle = styles;
  543.                 pAttributes = oldAttributes;
  544.                 for (i = 0; i < nStyles; ++i, ++pStyle, ++pAttributes)
  545.                     if (*pStyle != nil)
  546.                         GXSetStyleTextAttributes(*pStyle, *pAttributes);
  547.                         
  548.                 GXSetStyleTextAttributes(aStyle, oldMainAttributes);
  549.                 
  550.                 failed_changeType:
  551.                 // We're done, clean up .
  552.  
  553. failed_GetGlyphs1:
  554.                 DisposePtr((Ptr)styles);
  555.                                                 
  556.                 break;
  557.                 
  558.             default:
  559.                 break;
  560.             
  561.         }//end switch (theType);
  562.  
  563. failed_newptr:
  564. failed_GetGlyphs:
  565.         
  566.         return(status);
  567.     
  568.     }//TextToUnhintedPath
  569.  
  570.  
  571.